/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ee.ut.math.esi.service.response;

import com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import movierestsoapservice.AbridgedCast;
import movierestsoapservice.AlternateIds;
import movierestsoapservice.BrowseLinks;
import movierestsoapservice.BrowseServiceResponse;
import movierestsoapservice.Links;
import movierestsoapservice.Movies;
import movierestsoapservice.Posters;
import movierestsoapservice.Ratings;
import movierestsoapservice.ReleaseDates;
import movierestsoapservice.SearchServiceResponse;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 *
 * @author ool
 */
public class XML2SearchServiceResponse {

    public static SearchServiceResponse transformSearchServiceXml(String xml) throws SAXException, IOException, ParserConfigurationException {
        DocumentBuilderFactory dbf = new DocumentBuilderFactoryImpl();
        DocumentBuilder db = dbf.newDocumentBuilder();
        ByteArrayInputStream input = new ByteArrayInputStream(xml.getBytes());
        Document doc = db.parse(input);
        Node respNode = doc.getFirstChild();

        SearchServiceResponse resp = parseRespNode(respNode);
        return resp;
    }
    
    public static BrowseServiceResponse transformBrowseServiceXml(String xml, int limit) throws SAXException, IOException, ParserConfigurationException {
        
        SearchServiceResponse tempResp = transformSearchServiceXml(xml);
        
        BrowseServiceResponse resp = new BrowseServiceResponse();
        resp.setTotal(limit);
        resp.setLinks(tempResp.getLinks());
        resp.setLinkTemplate(tempResp.getLinkTemplate());
        resp.getMovies().addAll(tempResp.getMovies());
        
        return resp;
    }
    

    private static SearchServiceResponse parseRespNode(Node respNode) {
        SearchServiceResponse resp = new SearchServiceResponse();

        parseNodes(respNode.getChildNodes(), resp);
        return resp;
    }

    private static void parseNodes(NodeList resultNode, SearchServiceResponse resp) {

        for (int i = 0; i < resultNode.getLength(); i++) {
            Node node = resultNode.item(i);
            String nodeName = node.getNodeName();
            if ("total".equals(nodeName)) {
                resp.setTotal(Integer.parseInt(node.getTextContent()));
                continue;
            }
            if ("movies".equals(nodeName)) {
                parseMoviesNode(node, resp);
                continue;
            }
            if ("links".equals(nodeName)) {
                parseBrowseLinks(node, resp);
            }
        }
    }

    private static void parseMoviesNode(Node moviesNode, SearchServiceResponse resp) {
        Movies movie = new Movies();
        NodeList childNodes = moviesNode.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            parseMovieChildNode(childNodes.item(i), movie);
        }
        resp.getMovies().add(movie);
    }

    private static void parseMovieChildNode(Node movieChildNode, Movies movie) {
        String nodeName = movieChildNode.getNodeName();
        String content = movieChildNode.getTextContent();
        if ("id".equals(nodeName)) {
            movie.setId(movieChildNode.getTextContent());
            return;
        }
        if ("title".equals(nodeName)) {
            movie.setTitle(movieChildNode.getTextContent());
            return;
        }
        if ("year".equals(nodeName)) {
            movie.setYear(movieChildNode.getTextContent());
            return;
        }
        if ("mpaa_rating".equals(nodeName)) {
            movie.setMpaaRating(movieChildNode.getTextContent());
            return;
        }
        if ("runtime".equals(nodeName)) {
            movie.setRuntime(movieChildNode.getTextContent());
            return;
        }
        if ("critics_consensus".equals(nodeName)) {
            movie.setCriticsConsensus(movieChildNode.getTextContent());
            return;
        }
        if ("release_dates".equals(nodeName)) {
            parseReleaseDates(movieChildNode, movie);
            return;
        }
        if ("ratings".equals(nodeName)) {
            parseRatings(movieChildNode, movie);
            return;
        }
        if ("synopsis".equals(nodeName)) {
            movie.setSynopsis(movieChildNode.getTextContent());
            return;
        }
        if ("posters".equals(nodeName)) {
            parsePosters(movieChildNode, movie);
            return;
        }
        if ("abridged_cast".equals(nodeName)) {
            parseAbridgedCast(movieChildNode, movie);
            return;
        }
        if ("alternate_ids".equals(nodeName)) {
            parseAlternateIds(movieChildNode, movie);
            return;
        }
        if ("links".equals(nodeName)) {
            parseLinks(movieChildNode, movie);
            return;
        }
    }

    private static void parseReleaseDates(Node movieChildNode, Movies movie) {
        NodeList nodes = movieChildNode.getChildNodes();
        ReleaseDates releaseDates = new ReleaseDates();

        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if ("theater".equals(node.getNodeName())) {
                releaseDates.setTheater(node.getTextContent());
                continue;
            }
            if ("dvd".equals(node.getNodeName())) {
                releaseDates.setDvd(node.getTextContent());
                continue;
            }
        }
        movie.setReleaseDates(releaseDates);
    }

    private static void parseRatings(Node movieChildNode, Movies movie) {
        NodeList nodes = movieChildNode.getChildNodes();
        Ratings ratings = new Ratings();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            String nodeName = node.getNodeName();
            if ("critics_rating".equals(nodeName)) {
                ratings.setCriticsRating(node.getTextContent());
                continue;
            }
            if ("critics_score".equals(nodeName)) {
                ratings.setCriticsScore(node.getTextContent());
                continue;
            }
            if ("audience_rating".equals(nodeName)) {
                ratings.setAudienceRating(node.getTextContent());
                continue;
            }
            if ("audience_score".equals(nodeName)) {
                ratings.setAudienceScore(node.getTextContent());
                continue;
            }
        }
        movie.setRatings(ratings);
    }

    private static void parsePosters(Node movieChildNode, Movies movie) {
        Posters posters = new Posters();
        NodeList nodes = movieChildNode.getChildNodes();

        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            String nodeName = node.getNodeName();
            if ("thumbnail".equals(nodeName)) {
                posters.setThumbnail(node.getTextContent());
            }
            if ("profile".equals(nodeName)) {
                posters.setProfile(node.getTextContent());
            }
            if ("detailed".equals(nodeName)) {
                posters.setDetailed(node.getTextContent());
            }
            if ("original".equals(nodeName)) {
                posters.setOriginal(node.getTextContent());
            }
        }
        movie.setPosters(posters);
    }

    private static void parseAbridgedCast(Node movieChildNode, Movies movie) {
        NodeList nodes = movieChildNode.getChildNodes();

        AbridgedCast cast = new AbridgedCast();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if ("name".equals(node.getNodeName())) {
                cast.setName(node.getTextContent());
            }
            if ("characters".equals(node.getNodeName())) {
                cast.setCharacters(node.getTextContent());
            }
        }

        movie.getAbridgedCast().add(cast);
    }

    private static void parseAlternateIds(Node movieChildNode, Movies movie) {
        AlternateIds altIds = new AlternateIds();
        altIds.setImdb(movieChildNode.getFirstChild().getTextContent());

        movie.setAlternateIds(altIds);
    }

    private static void parseLinks(Node movieChildNode, Movies movie) {
        Links links = new Links();

        NodeList nodes = movieChildNode.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            String nodeName = node.getNodeName();
            if ("self".equals(nodeName)) {
                links.setSelf(node.getTextContent());
                continue;
            }
            if ("alternate".equals(nodeName)) {
                links.setAlternate(node.getTextContent());
                continue;
            }
            if ("cast".equals(nodeName)) {
                links.setCast(node.getTextContent());
                continue;
            }
            if ("clips".equals(nodeName)) {
                links.setClips(node.getTextContent());
                continue;
            }
            if ("reviews".equals(nodeName)) {
                links.setReviews(node.getTextContent());
                continue;
            }
            if ("similar".equals(nodeName)) {
                links.setSimilar(node.getTextContent());
                continue;
            }
        }
        movie.setLinks(links);
    }

    private static void parseBrowseLinks(Node linksNode, SearchServiceResponse resp) {
        NodeList nodes = linksNode.getChildNodes();
        BrowseLinks links = new BrowseLinks();
        for (int i=0; i< nodes.getLength(); i++) {
            Node node = nodes.item(i);
            String nodeName = node.getNodeName();
            if ("prev".equals(nodeName)) {
                links.setPrev(node.getTextContent());
                continue;
            }
            if ("self".equals(nodeName)) {
                links.setSelf(node.getTextContent());
                continue;
            }
            if ("next".equals(nodeName)) {
                links.setNext(node.getTextContent());
                continue;
            }
        }
    }
}
